package com.practice.httputils.trustallcerts;


import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.StandardHttpRequestRetryHandler;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Objects;

/**
 * @Description : httpComponents httpclient工具
 * @Version : V1.0.0
 * @Date : 2023/1/3 17:46
 */
public class HttpClientUtil {

    /**
     * 忽视所有证书验证-使用org.apache.httpcomponents 4.5版本
     *
     * @return
     */
    public static CloseableHttpClient trustAllCertsHttpClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
            // 忽略证书校验
            @Override
            public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                return true;
            }
        }).build();
        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE);
        final Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", sslConnectionSocketFactory).build();
        // 5秒超时
        RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(5000)
                .setSocketTimeout(10000).setConnectTimeout(10000).build();
        SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(5000).build();
        PoolingHttpClientConnectionManager cm =
                new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        cm.setMaxTotal(300);
        // 单路由最大并发数
        cm.setDefaultMaxPerRoute(30);
        return HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setRetryHandler(new StandardHttpRequestRetryHandler())
                .setDefaultSocketConfig(socketConfig).setConnectionManager(cm).build();
    }

    private static String sendPostHttpRequestWithTimeOut(String reqURL, String param, Map<String, String> headerMap, int readTimeout) throws HttpException {
        String result = "-1";
        HttpPost httpPost = new HttpPost(reqURL);
        httpPost.setHeader(HTTP.CONTENT_TYPE, "application/json; charset=" + "UTF-8");
        CloseableHttpResponse response = null;
        try {
            if (param != null) {
                StringEntity entity = new StringEntity(param, "UTF-8");
                httpPost.setEntity(entity);
                if (!Objects.isNull(headerMap) && headerMap.size() != 0) {
                    for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                        httpPost.addHeader(entry.getKey(), entry.getValue());
                    }
                }
            }
            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(3000).setConnectTimeout(4000)
                    .setSocketTimeout(readTimeout).build();
            httpPost.setConfig(requestConfig);
            response = trustAllCertsHttpClient().execute(httpPost, HttpClientContext.create());
            HttpEntity entity = response.getEntity();
            if (null != entity) {
                result = EntityUtils.toString(entity, ContentType.getOrDefault(entity).getCharset());
                EntityUtils.consume(entity);
            }
        } catch (Exception e) {
            throw new HttpException("请求通信[" + reqURL + "]时读取超时，堆栈轨迹如下：", e);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (httpPost != null) {
                httpPost.releaseConnection();
            }
        }
        return result;
    }

    public static void main(String[] args) throws HttpException {
        JSONObject js = new JSONObject();
        js.put("user", "minivision132dddd34f");
        js.put("innetIp", "127.0.0.1");
        final String result = sendPostHttpRequestWithTimeOut("http://172.16.6.86:5015/file/auth/getToken", js.toString(), null, 3000);
        System.out.println(result);

        final String get = sendPostHttpRequestWithTimeOut("https://www.baidu.com/", null, null, 1000);
        System.out.println(get);
    }
}
